#include "anim.h"
#include "video.h"

#define SWAPWORDHLVS(val) ( ((val&0xFF000000) >> 8)+((val&0x00FF0000) << 8) + ((val&0x0000FF00) >> 8)+((val&0x000000FF) << 8))
#define SWAPLONG(val) (((val&0xFFFF0000) >> 16) + ((val&0x0000FFFF) << 16)) 
long fixlong(long l)
{
    long swapnyb = ( ( ((l&0xF0000000)>>4) + ((l&0x0F000000)<<4) ) +  ( ((l&0x00F00000)>>4) + ((l&0x000F0000)<<4) ) + ( ((l&0x0000F000)>>4) + ((l&0x00000F00)<<4) ) + ( ((l&0x000000F0)>>4) + ((l&0x0000000F)<<4) ));
    return SWAPWORDHLVS(l);
}
//; ---------------------------------------------------------------------------
//; Animated uncompressed graphics
//; ---------------------------------------------------------------------------
//Art_GhzWater:	incbin	"artunc\GHZ Waterfall.bin"
//		even
extern byte Art_GhzWater[];
extern byte Art_GhzFlower1[];
extern byte Art_GhzFlower2[];

/*
Art_GhzFlower1:	incbin	"artunc\GHZ Flower Large.bin"
		even
Art_GhzFlower2:	incbin	"artunc\GHZ Flower Small.bin"
		even
Art_MzLava1:	incbin	"artunc\MZ Lava Surface.bin"
		even
Art_MzLava2:	incbin	"artunc\MZ Lava.bin"
		even
Art_MzTorch:	incbin	"artunc\MZ Background Torch.bin"
		even
Art_SbzSmoke:	incbin	"artunc\SBZ Background Smoke.bin"
		even
*/
extern word *vRam;

extern bool f_pause;

extern byte v_zone;


byte v_lani0_frame, v_lani1_frame, v_lani2_frame, v_lani3_frame, v_lani4_frame, v_lani5_frame;
signed char v_lani0_time, v_lani1_time, v_lani2_time, v_lani3_time, v_lani4_time, v_lani5_time;

signed char v_ani0_time, v_ani1_time, v_ani2_time, v_ani3_time;
byte v_ani0_frame, v_ani1_frame, v_ani2_frame, v_ani3_frame;

signed short v_ani3_buf;

void SynchroAnimate()
{
    //SynchroAnimate:				; XREF: GM_Level

    //; Used for GHZ spiked log
    //Sync1:
    //subq.b	#1,(v_ani0_time).w ; has timer reached 0?
    v_ani0_time = v_ani0_time - 1;

    //bpl.s	Sync2		; if not, branch
    if (v_ani0_time < 0)
    {
        //move.b	#$B,(v_ani0_time).w ; reset timer
        v_ani0_time = 11;
        
	//subq.b	#1,(v_ani0_frame).w ; next frame
        v_ani0_frame = v_ani0_frame - 1;

	//andi.b	#7,(v_ani0_frame).w ; max frame is 7
        v_ani0_frame = v_ani0_frame & 7;
    }

    //; Used for rings and giant rings
    //Sync2:
    //subq.b	#1,(v_ani1_time).w
    v_ani1_time = v_ani1_time - 1;

    //bpl.s	Sync3
    if (v_ani1_time < 0)
    {
        //move.b	#7,(v_ani1_time).w
        v_ani1_time = 7;

        //addq.b	#1,(v_ani1_frame).w
        v_ani1_frame = v_ani1_frame + 1;

	//andi.b	#3,(v_ani1_frame).w
        v_ani1_frame = v_ani1_frame & 3;
    }

    //; Used for nothing
    //Sync3:
    //subq.b	#1,(v_ani2_time).w
    v_ani2_time = v_ani2_time - 1;

    //bpl.s	Sync4
    if (v_ani2_time < 0)
    {
        //move.b	#7,(v_ani2_time).w
        v_ani2_time = 7;

        //addq.b	#1,(v_ani2_frame).w
        v_ani2_frame = v_ani2_frame + 1;

	//cmpi.b	#6,(v_ani2_frame).w
        //blo.s	Sync4
        if (v_ani2_frame >= 6)
        {
	    //move.b	#0,(v_ani2_frame).w
            v_ani2_frame = 0;
        }
    }

    //; Used for bouncing rings
    //Sync4:
    //tst.b	(v_ani3_time).w
    if (v_ani3_time != 0)
    {
        //beq.s	SyncEnd
 	//moveq	#0,d0
	//move.b	(v_ani3_time).w,d0
	//add.w	(v_ani3_buf).w,d0
        word newani3_time = (byte)v_ani3_time + v_ani3_buf;
        
	//move.w	d0,(v_ani3_buf).w
        v_ani3_buf = newani3_time;

	//rol.w	#7,d0
	//andi.w	#3,d0
        byte newani3_frame = ((newani3_time << 7) | (newani3_time >> 9)) & 3;

	//move.b	d0,(v_ani3_frame).w
        v_ani3_frame = newani3_frame;

	//subq.b	#1,(v_ani3_time).w
        v_ani3_time = v_ani3_time - 1;
    }
    //SyncEnd:
    //rts
}   //; End of function SynchroAnimate


#define Ani_Art_none 0
void (*AniArt_Index[7])() = { AniArt_GHZ, Ani_Art_none, Ani_Art_none/*AniArt_MZ*/, Ani_Art_none, Ani_Art_none, Ani_Art_none/*Ani_Art_SBZ*/, Ani_Art_none/*Ani_Art_Ending*/ };

long *vRamWrite = (long*)vRam;
#define locVRAM(addr) vRamWrite = ((long*)vRam) + (addr/4);

//; ---------------------------------------------------------------------------
//; Subroutine to	animate	level graphics
//; ---------------------------------------------------------------------------

//AnimateLevelGfx:			; XREF: Demo_Time; VBla_0C_NoChg
void AnimateLevelGfx()
{
    
    //tst.w	(f_pause).w	; is the game paused?
    //bne.s	@ispaused	; if yes, branch
    if (!f_pause)
    {
        //lea	(vdp_data_port).l,a6
	
        //bsr.w	AniArt_GiantRing                 //giant special stage ring has its own routine for it is specific of all levels
	
        //moveq	#0,d0
        //move.b	(v_zone).w,d0
	//add.w	d0,d0
        byte zone = v_zone;

	//move.w	AniArt_Index(pc,d0.w),d0
	//jmp	AniArt_Index(pc,d0.w)
        (*AniArt_Index[zone])();

    }
    
    //@ispaused:
    //rts
    
}	

void AniArt_GHZ()
{
    //; ===========================================================================
    //; ---------------------------------------------------------------------------
    //; Animated pattern routine - Green Hill
    //; ---------------------------------------------------------------------------

    //AniArt_GHZ:				; XREF: AniArt_Index
    //AniArt_GHZ_Waterfall:

    //@size:		= 8	; number of tiles per frame
    #define size 8
 
    //subq.b	#1,(v_lani0_time).w ; decrement timer
    v_lani0_time = v_lani0_time - 1;

    //bpl.s	AniArt_GHZ_Bigflower ; branch if not 0
    if (v_lani0_time < 0)
    {
        //move.b	#5,(v_lani0_time).w ; time to display each frame
        v_lani0_time = 5;
        	
	//lea	(Art_GhzWater).l,a1 ; load waterfall patterns
        long *patternDataPtr = (long*)Art_GhzWater;
        
	//move.b	(v_lani0_frame).w,d0
        byte frameCounter = v_lani0_frame;
 
	//addq.b	#1,(v_lani0_frame).w ; increment frame counter
        v_lani0_frame = v_lani0_frame + 1;

	//andi.w	#1,d0		; there are only 2 frames
        word frame = frameCounter & 1;
         
	//beq.s	@isframe0	; branch if frame 0
        if (frame != 0)
        {
	    //lea	@size*$20(a1),a1 ; use graphics for frame 1
            patternDataPtr = patternDataPtr + ((0x20*size)/4);
        }
         
	//@isframe0:
	//locVRAM	$6F00		; VRAM address
        locVRAM(0x6F00); 

        //move.w	#@size-1,d1	; number of 8x8	tiles
	word numTiles = size-1;

        LoadTiles(patternDataPtr, numTiles, 0x6F00);
    }

    //; ===========================================================================
    //AniArt_GHZ_Bigflower:

    #undef size
    //@size:		= 16	; number of tiles per frame
    #define size 16

    //subq.b	#1,(v_lani1_time).w
    v_lani1_time = v_lani1_time - 1;

    //bpl.s	AniArt_GHZ_Smallflower
    if (v_lani1_time < 0)
    {
        //move.b	#$F,(v_lani1_time).w
        v_lani1_time = 0xF;
        
	//lea	(Art_GhzFlower1).l,a1 ;	load big flower	patterns
        long *patternDataPtr = (long*)Art_GhzFlower1;

	//move.b	(v_lani1_frame).w,d0
        byte frameCounter = v_lani1_frame;
 
	//addq.b	#1,(v_lani1_frame).w
        v_lani1_frame = v_lani1_frame + 1;

	//andi.w	#1,d0
        word frame = frameCounter & 1;

	//beq.s	@isframe0
        if (frame != 0)
        {
	    //lea	@size*$20(a1),a1
            patternDataPtr = patternDataPtr + ((0x20*size)/4);
        }

	//@isframe0:
	//locVRAM	$6B80
        locVRAM(0x6B80);

	//move.w	#@size-1,d1
        word numTiles = size-1;
	
        //bra.w	LoadTiles
        LoadTiles(patternDataPtr, numTiles, 0x6B80);
    }

    //; ===========================================================================
    //AniArt_GHZ_Smallflower:
    
    //subq.b	#1,(v_lani2_time).w
    v_lani2_time = v_lani2_time - 1;

    //bpl.s	@end
    if (v_lani2_time < 0)
    {
        //move.b	#7,(v_lani2_time).w
        v_lani2_time = 7;
 
	//move.b	(v_lani2_frame).w,d0
        byte frameCounter = v_lani2_frame;

	//addq.b	#1,(v_lani2_frame).w ; increment frame counter
        v_lani2_frame = v_lani2_frame + 1;

        //andi.w	#3,d0		; there are 4 frames
        word frame = frameCounter & 3;

        byte sequence[4] = { 0, 1, 2, 1 };
        
        //move.b	@sequence(pc,d0.w),d0
	byte frameNum = sequence[frame];
 
        //btst	#0,d0		; is frame 0 or 2? (actual frame, not frame counter)
        //bne.s	@isframe1	; if not, branch
	if ((frameNum & 1) == 1)
        {
 	    //move.b	#$7F,(v_lani2_time).w ; set longer duration for frames 0 and 2
            v_lani2_time = 0x7F;
        }

	//@isframe1:
	//lsl.w	#7,d0		; multiply frame num by $80
        //move.w	d0,d1
	//add.w	d0,d0
	//add.w	d1,d0		; multiply that by 3
        word tileOffset = frameNum * 384;

	//locVRAM	$6D80
        locVRAM(0x6D80);
 
	//lea	(Art_GhzFlower2).l,a1 ;	load small flower patterns
        long *patternDataPtr = (long*)Art_GhzFlower2;

	//lea	(a1,d0.w),a1	; jump to appropriate tile
        patternDataPtr = patternDataPtr + (tileOffset/4);

	//move.w	#$B,d1
        word numTiles = 0xB; 

	//bsr.w	LoadTiles
        LoadTiles(patternDataPtr, numTiles, 0x6D80);

        //@end:
    }   //rts	

    //@sequence:	dc.b 0,	1, 2, 1

    //AniArt_none:				; XREF: AniArt_Index
}   //rts	

void LoadTiles(long *tileData, signed short numTiles, word vramAddr)
{
    locVRAM(vramAddr); //additionally

    //; ---------------------------------------------------------------------------
    //; Subroutine to	load (d1 - 1) 8x8 tiles
    //; ---------------------------------------------------------------------------

    //; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||

    //LoadTiles:
    for ( ;numTiles>=0; numTiles--)
    {
        //move.l	(a1)+,(a6)
        *(vRamWrite++) = fixlong(*(tileData++));
 
        //move.l	(a1)+,(a6)
        *(vRamWrite++) = fixlong(*(tileData++));

        //move.l	(a1)+,(a6)
        *(vRamWrite++) = fixlong(*(tileData++));

        //move.l	(a1)+,(a6)
        *(vRamWrite++) = fixlong(*(tileData++));

        //move.l	(a1)+,(a6)
        *(vRamWrite++) = fixlong(*(tileData++));

        //move.l	(a1)+,(a6)
        *(vRamWrite++) = fixlong(*(tileData++));

        //move.l	(a1)+,(a6)
        *(vRamWrite++) = fixlong(*(tileData++));

        //move.l	(a1)+,(a6)
        *(vRamWrite++) = fixlong(*(tileData++));
    
    }   //dbf	d1,LoadTiles
    //rts
} //; End of function LoadTiles

/*; ==========================================================================

; ---------------------------------------------------------------------------
; Animated pattern routine - giant ring
; ---------------------------------------------------------------------------

; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


AniArt_GiantRing:			; XREF: AnimateLevelGfx
		tst.w	(v_gfxbigring).w
		bne.s	loc_1C518
		rts	
; ===========================================================================

loc_1C518:
		subi.w	#$1C0,(v_gfxbigring).w
		lea	(Art_BigRing).l,a1 ; load giant	ring patterns
		moveq	#0,d0
		move.w	(v_gfxbigring).w,d0
		lea	(a1,d0.w),a1
		addi.w	#$8000,d0
		lsl.l	#2,d0
		lsr.w	#2,d0
		ori.w	#$4000,d0
		swap	d0
		move.l	d0,4(a6)
		move.w	#$D,d1
		bra.w	LoadTiles

; End of function AniArt_GiantRing
*/
